/**
 * @file exampleSolverEqu.cpp
 * @author shikang999@126.com
 * @brief 这个例子主要演示如何求解非线性方程组
 * @version 0.1
 * @date 2025-06-23
 * 
 * @copyright Copyright (c) 2025
 * 
 */

#include "SolverFun.h"
#include "BaseFun.h"
#include "HelpFun.h"

#include <sstream>
#include <iomanip>
#include "DumpLog.h"

using namespace Solver;
class Fun : public BaseFun
{
public:
    Fun(std::size_t dim):   BaseFun(dim,
                            FunType_E::Nohting_E, 
                            DifficultyLevel_E::Nothing_E,
                            1,
                            "",
                            "")
    {

    }

    ~Fun()
    {

    }

    //在这个函数里定义方程
    value_t calcFun(const VectorXd_t &a)
    {
        /*
        求解下面的方程组 
        4.5/cos(y/z) - sin(x)*log(y) = 4.959
        sin(z/(x^2 + y^2)*3)         = -0.9498
        y^2/(x + z)                  = -1.5864
        sin(z) *x -cos(x*y)          = 2.447
        */
        value_t x = a[0];
        value_t y = a[1];
        value_t z = a[2];

        value_t f =  std::pow(4.5 / std::cos(y/z) - std::sin(x) * std::log(y) - 4.959, 2)    +
                        std::pow(std::sin(z/(x * x + y * y) * 3) + 0.9498, 2)                +
                        std::pow(y * y / (x + z) + 1.5864, 2)                                +
                        std::pow(std::sin(z) * x - std::cos(x * y) - 2.447, 2);
        
        return std::isnan(f) ? 1e300 : f;
    }
};

int main()
{
    //1.设置需要测试的函数
    std::shared_ptr<BaseFun> fun = std::make_shared<Fun>(3);//这里3表示上面方程组变量维度,即x,y,z
    
    //2.设置需要测试的求解器
    auto solver = SolverFun::SolverFun::getSolver(SolverType_E::SWO_E);

    //3.设置迭代条件
    Solver::value_t minErr = 0;     //迭代终止目标,当目标函数值小于此值时停止迭代
    std::size_t iterSum    = 10000; //最大迭代次数

    //4.设置变量范围
    Solver::value_t minVar = -10000; //变量下限
    Solver::value_t maxVar = 10000;  //变量上限

    //5.设置种群数量
    std::size_t popNum = 90;

    //6.求解
    {
        //6.1 设置基本参数
        solver->setFun(fun);
        solver->setVarRange(minVar, maxVar, fun->getDim());
        solver->getCondition().limitError = minErr;
        solver->getCondition().limitIter  = iterSum;
        solver->setPrintNum(50);//间隔50次打印一次结果

        //6.2 求解
        solver->solve(popNum);
        solver->waitExit();

        //6.3 获取结果
        auto res = solver->getResult();

        //6.4 打印
        std::ostringstream ss;
        ss << std::setprecision(16);
        ss  << "\n------------------------------------------\n"
            << "最终目标值:"    << solver->getResult()->y                      << "\n"
            << "最终优化值:[\n" << Help::printVecValue(solver->getResult()->x) << "]\n"
            << "------------------------------------------\n";
        
        LogInfo(ss.str());
    }

    return 0;
}